﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using Telerik.Web.Mvc;
using Transport.Areas.Administrator.Models;
using Transport.Core.Models.Parcels;
using Transport.Core.Models.Users;
using Transport.Infrastructure;
using Transport.Infrastructure.Mvc;
using Transport.Infrastructure.Security;
using Transport.Services;
using Transport.Services.Infrastructure;
using Transport.Services.Parcels;
using Transport.Services.Settings;
using Transport.Services.Users;
using System.Data.Entity;

namespace Transport.Areas.Administrator.Controllers
{
    [Authorize]
    public class ParcelDeliveryController : ControllerBase<IUserRepository, User>
    {
        private readonly IParcelDeliveryGroupRepository _parcelDeliveryGroupRepository;
        private readonly IParcelDeliveryRepository _parcelDeliveryRepository;
        private readonly IParcelRepository _parcelRepository;
        private readonly ITrackingRepository _trackingRepository;
        private readonly IStateProvinceRepository _stateProvinceRepository;
        private readonly IParcelDeliveryService _parcelDeliveryService;
        private readonly IStateProvinceBelongToRegionRepository _stateProvinceBelongToRegionRepository;

        public ParcelDeliveryController(IUnitOfWork unitOfWork, IUserRepository repository,
                                        IParcelDeliveryGroupRepository parcelDeliveryGroupRepository,
                                        IParcelDeliveryRepository parcelDeliveryRepository, IParcelRepository parcelRepository,
                                        ITrackingRepository trackingRepository, IStateProvinceRepository stateProvinceRepository,
                                        IParcelDeliveryService parcelDeliveryService, IStateProvinceBelongToRegionRepository stateProvinceBelongToRegionRepository)
            : base(repository, unitOfWork)
        {
            _parcelDeliveryRepository = parcelDeliveryRepository;
            _parcelDeliveryGroupRepository = parcelDeliveryGroupRepository;
            _parcelRepository = parcelRepository;
            _trackingRepository = trackingRepository;
            _stateProvinceRepository = stateProvinceRepository;
            _parcelDeliveryService = parcelDeliveryService;
            _stateProvinceBelongToRegionRepository = stateProvinceBelongToRegionRepository;
        }

        #region Nhân Viên Phát

        public ActionResult Index()
        {
            return View();
        }
        
        //Hiện danh sách nhân viên phát bưu phẩm
        [GridAction]
        public ActionResult GridModel(string search)
        {
            //Chỉ hiển thị nhân viên là Nhân Viên Giao Nhận hoặc Nhân Viên Khai Thác
            var user = Repository.Search(search).Where(p => p.MyOfficeId == WorkContext.MyOfficeId 
                                                    && (p.Roles.Select(o => o.RoleName).Contains(RoleType.NVGiaoNhan) || 
                                                    p.Roles.Select(o => o.RoleName).Contains(RoleType.KhaiThac)));

            var gridModel = new GridModel<UserModel>
            {
                Data = user.Select(x => new UserModel
                {
                    UserId = x.UserId,
                    Email = x.EmailAddress,
                    FirstName = x.FirstName,
                    LastName = x.LastName,
                    IsLockedOut = x.IsLockedOut,
                    CreateDate = x.CreateDate.Value
                })
            };
            return new JsonResult
            {
                Data = gridModel
            };
        }

        public ActionResult User(int id)
        {
            var user = Repository.GetAll().FirstOrDefault(p => p.UserId == id);
            var userModel = new UserModel()
            {
                UserId = user.UserId,
                FirstName = user.FirstName,
                LastName = user.LastName,
                Email = user.EmailAddress
            };
            
            return View(userModel);
        }

        //Danh sách các đợt phát theo nhân viên
        [GridAction]
        public ActionResult GridDeliveryGroupModel(string search, int id)
        {
            var users = from x in _parcelDeliveryGroupRepository.Search(search)
                        join u in Repository.GetAll() on x.CreateUserId equals u.UserId
                        where x.DeliveryUserId == id
                        select new ParcelDeliveryGroupModel
                        {
                            CreateDate = x.CreateDate,
                            ParcelDeliveryGroupId = x.ParcelDeliveryGroupId,
                            CreateUser = u.FirstName + u.LastName
                        };

            var gridModel = new GridModel<ParcelDeliveryGroupModel>
            {
                Data = users
            };
            return new JsonResult
            {
                Data = gridModel
            };
        }

        public ActionResult Create(int id)
        {
            var entity = new ParcelDeliveryGroup()
            {
                CreateDate = DateTime.Now,
                CreateUserId = WorkContext.CurrentUserId,
                MyOfficeId = WorkContext.MyOfficeId,
                DeliveryUserId = id,
                ParcelDeliverys = new List<ParcelDelivery>()
                
            };
            using (UnitOfWork)
            {
                _parcelDeliveryGroupRepository.Insert(entity);
            }

            return RedirectToAction("Edit", new { id = entity.ParcelDeliveryGroupId });
        }

        public ActionResult Edit(int id)
        {
            var entity = _parcelDeliveryGroupRepository.GetAll().Where(p => p.ParcelDeliveryGroupId == id).Include(o => o.User).FirstOrDefault();
            var model = new ParcelDeliveryGroupModel()
            {
                CreateDate = entity.CreateDate,
                DeliveryUser = entity.User.FirstName + " " + entity.User.LastName,
                ParcelDeliveryGroupId = entity.ParcelDeliveryGroupId,
                DeliveryUserId = entity.DeliveryUserId
            };

            return View(model);
        }
        
        #endregion

        #region Phát Cho Nhân Viên

        [OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
        public ActionResult DownloadParcelDelivery(int id)
        {
            var fileName = string.Format("BuuPhamDiPhat_{0}", DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss"));
            return PdfResult(_parcelDeliveryService.DownloadParcelDelivery(id, WorkContext.MyOfficeId), fileName);
        }

        [GridAction]
        public ActionResult GridDeliveryModel(string search, int id)
        {
            var data = from x in _parcelDeliveryRepository.Search(string.Empty).Include(p => p.Parcel)
                       join s in _stateProvinceRepository.GetAll() on x.Parcel.DeliverToId equals s.StateProvinceId
                        where x.ParcelDeliveryGroupId == id
                        select new ParcelDeliveryModel
                        {
                            CreateDate = x.CreateDate,
                            ParcelDeliveryGroupId = x.ParcelDeliveryGroupId,
                            ToAddress = x.Parcel.ToAddress,
                            TrackingNumbers = x.Parcel.TrackingNumbers,
                            TotalCost = x.Parcel.TotalCost,
                            TotalWeight = x.Parcel.TotalWeight,
                            ParcelDeliveryId = x.ParcelDeliveryId,
                            DeliverTo = s.StateProvinceName,
                            Receiver = x.Parcel.Receiver,
                            ReceivedDate = x.Parcel.ReceivedDate,
                            Status = x.Parcel.Status
                        };

            var gridModel = new GridModel<ParcelDeliveryModel>
            {
                Data = data
            };
            return new JsonResult
            {
                Data = gridModel
            };
        }

        public ActionResult AllocatedToPostman(string search, int id)
        {
            if (!string.IsNullOrEmpty(search))
            {
                var parcel = _parcelRepository.GetAll().FirstOrDefault(p => p.TrackingNumbers == search);
                if (parcel != null
                    && parcel.Status >= (int)TrackingStatus.EnumTrackingStatus.BeForwarding
                    && parcel.Status <= (int)TrackingStatus.EnumTrackingStatus.AllocatedToPostman
                    && (parcel.DeliverToOfficeId == WorkContext.MyOfficeId || (parcel.MyOfficeId == WorkContext.MyOfficeId && parcel.IsEms)))
                {
                    var parcelDeliveryGroup = _parcelDeliveryGroupRepository.GetAll().FirstOrDefault(p => p.ParcelDeliveryGroupId == id);
                    var parcelDelivery = new ParcelDelivery
                    {
                        CreateDate = DateTime.Now,
                        DeliveryUserId = parcelDeliveryGroup.DeliveryUserId,
                        ParcelDeliveryGroupId = id,
                        ParcelId = parcel.ParcelId
                    };

                    var stateProvinceId = _stateProvinceRepository.GetAll()
                                            .Where(p => p.IsMain && p.MyOfficeId == WorkContext.MyOfficeId)
                                            .Select(o => o.StateProvinceId).FirstOrDefault();
                    var trackingAllocatedToPostman = new Tracking
                    {
                        CreateDate = DateTime.Now,
                        DateOfSending = DateTime.Now,
                        IsDeleted = false,
                        ParcelId = parcel.ParcelId,
                        StateProvinceId = stateProvinceId,
                        Status = (int)TrackingStatus.EnumTrackingStatus.AllocatedToPostman,
                        UserId = WorkContext.CurrentUserId
                    };
                    var trackingDeliver = new Tracking
                    {
                        CreateDate = DateTime.Now,
                        DateOfSending = DateTime.Now,
                        IsDeleted = false,
                        ParcelId = parcel.ParcelId,
                        StateProvinceId = stateProvinceId,
                        Status = (int)TrackingStatus.EnumTrackingStatus.Deliver,
                        UserId = parcelDeliveryGroup.DeliveryUserId
                    };
                    using (UnitOfWork)
                    {
                        _parcelDeliveryRepository.Insert(parcelDelivery);
                        _trackingRepository.Insert(trackingAllocatedToPostman);
                        _trackingRepository.Insert(trackingDeliver);
                        parcel.Status = (int)TrackingStatus.EnumTrackingStatus.Deliver;
                        _parcelRepository.Update(parcel);
                    }
                    return Json(true);
                }
            }

            return Json(false);
        }

        public ActionResult DeleteDeliveryItem(int id)
        {
            int parcelDeliveryGroupId = 0;
            try
            {
                var parcelDelivery = _parcelDeliveryRepository.GetById(id);
                parcelDeliveryGroupId = parcelDelivery.ParcelDeliveryGroupId;
                var parcel = _parcelRepository.GetById(parcelDelivery.ParcelId);
                if (parcel.Status > (int)TrackingStatus.EnumTrackingStatus.Deliver)
                {
                    SetErrorNotification("Bill này không thể xóa!");
                    return RedirectToAction("Edit", "ParcelDelivery", new { area = "Administrator", id = parcelDeliveryGroupId });
                }
                using (UnitOfWork)
                {
                    var trackings = _trackingRepository.GetAll().Where(p => p.ParcelId == parcelDelivery.ParcelId && (p.Status == (int)TrackingStatus.EnumTrackingStatus.AllocatedToPostman || p.Status == (int)TrackingStatus.EnumTrackingStatus.Deliver));
                    foreach (var tracking in trackings)
                    {
                        tracking.IsDeleted = true;
                    }
                    parcel.Status = (int)TrackingStatus.EnumTrackingStatus.BeForwarding;
                    _parcelRepository.Update(parcel);
                    _parcelDeliveryRepository.Delete(id);
                }
                SetSuccessNotification("Bill đã được xóa thành công.");
            }
            catch
            {
                SetErrorNotification("Bill này không thể xóa, vì đã được sử dụng!");
            }
            return RedirectToAction("Edit", "ParcelDelivery", new { id = parcelDeliveryGroupId, area = "Administrator" });
        }

        #endregion

        #region Phát Thành Công

        public virtual ActionResult DeliverySuccess()
        {
            var parcelLeft = _parcelDeliveryRepository.GetAll().Count(p => p.DeliveryUserId == WorkContext.CurrentUserId && p.Parcel.Status < (int)TrackingStatus.EnumTrackingStatus.Success);
            var model = new DeliverySuccessModel 
            {
                ReceivedDate = DateTime.Now,
                ParcelLeft = parcelLeft
            };
            return View(model);
        }
        [HttpPost]
        public virtual ActionResult DeliverySuccess(DeliverySuccessModel model)
        {
            if (!ModelState.IsValid)
            {
                return View(model);
            }
            //Check existed
            var parcel = _parcelRepository.GetAll().FirstOrDefault(p => p.TrackingNumbers == model.TrackingNumbers);
            if (parcel == null)
            {
                SetErrorNotification("Số vận đơn này không tồn tại trong hệ thống.");
                return View(model);
            }
            if (parcel.Status >= (int)TrackingStatus.EnumTrackingStatus.Success)
            {
                SetErrorNotification("Bưu phẩm này đã được báo phát thành công.");
                return View(model);
            }
            if (parcel.Status < (int)TrackingStatus.EnumTrackingStatus.Deliver)
            {
                SetErrorNotification("Bưu phẩm này chưa được giao nhân viên phát.");
                return View(model);
            }
            var tracking = new Tracking
            {
                CreateDate = DateTime.Now,
                DateOfSending = model.ReceivedDate,
                IsDeleted = false,
                ParcelId = parcel.ParcelId,
                Status = (int)TrackingStatus.EnumTrackingStatus.Success,
                StateProvinceId = parcel.DeliverToId,
                UserId = WorkContext.CurrentUserId
            };
            using (UnitOfWork)
            {
                _trackingRepository.Insert(tracking);
                if (!string.IsNullOrEmpty(model.Receiver))
                {
                    parcel.ReceivedDate = model.ReceivedDate;
                    parcel.Receiver = model.Receiver;
                    parcel.Status = (int)TrackingStatus.EnumTrackingStatus.Success;
                    _parcelRepository.Update(parcel);
                }

            }
            //Save success
            SetSuccessNotification(string.Format("{0} đã được phát thành công.", "Bưu phẩm"));
            return RedirectToAction("DeliverySuccess", new { area = "Administrator" });
        }

        #endregion
    }
}